import {unrefElement} from '@vueuse/core'

export function deepCopy(target) {
    // 定义一个变量
    let result
    // 如果当前需要深拷贝的是一个对象的话
    if (typeof target === 'object') {
        // 如果是一个数组的话
        if (Array.isArray(target)) {
            result = [] // 将result赋值为一个数组，并且执行遍历
            for (let i in target) {
                // 递归克隆数组中的每一项
                result.push(deepCopy(target[i]))
            }
            // 判断如果当前的值是null的话；直接赋值为null
        } else if (target === null) {
            result = null
            // 判断如果当前的值是一个RegExp对象的话，直接赋值
        } else if (target.constructor === RegExp) {
            result = target
        } else if (target instanceof Date) {
            result = target
        } else {
            // 否则是普通对象，直接for in循环，递归赋值对象的所有值
            result = {}
            for (let i in target) {
                result[i] = deepCopy(target[i])
            }
        }
        // 如果不是对象的话，就是基本数据类型，那么直接赋值
    } else {
        result = target
    }
    // 返回最终结果
    return result
}

export function isInArray(val, array) {
    if (array) {
        let index = array.length
        while (index--
            ) {
            if (array[index] === val) {
                return true
            }
        }
        return false
    } else {
        return false
    }
}

import CryptoJS from 'crypto-js'

export const getMd5 = (word) => {
    return CryptoJS.MD5(word).toString()
}

const AES_KEY = '@!o#$%2*7%&5(0!9'; // 16字节密钥（128位）

// 加密（返回Base64格式的IV+密文）
export function encrypt(data, aesKey) {
    const key = CryptoJS.enc.Utf8.parse(aesKey || AES_KEY);
    const iv = CryptoJS.lib.WordArray.random(16); // 生成16字节随机IV
    const encrypted = CryptoJS.AES.encrypt(data, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    return iv.concat(encrypted.ciphertext).toString(CryptoJS.enc.Base64);
}

// 解密（处理含IV的Base64字符串）
export function decrypt(encryptedData, aesKey) {
    const key = CryptoJS.enc.Utf8.parse(aesKey || AES_KEY);
    const dataBytes = CryptoJS.enc.Base64.parse(encryptedData);
    const iv = CryptoJS.lib.WordArray.create(dataBytes.words.slice(0, 4)); // 提取前16字节作为IV
    const ciphertext = CryptoJS.lib.WordArray.create(dataBytes.words.slice(4));
    const decrypted = CryptoJS.AES.decrypt(
        {ciphertext: ciphertext},
        key,
        {iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}
    );
    return decrypted.toString(CryptoJS.enc.Utf8);
}

export function setNull(val) {
    //不能直接判断(val),存在0的情况会被判断成false
    if (isInArray(val, [null, undefined, '']) || val.toString().trim() === '') {
        return null
    } else {
        return val
    }
}

export function checkNull(val) {
    return setNull(val) === null
}

export function checkNotNull(val) {
    return setNull(val) !== null
}

export function ArrayRemove(val, array) {
    let index = array.indexOf(val)
    if (index > -1) {
        array.splice(index, 1)
    }
}

//两个时间相减,一个时间则是和当前时间比
export function transferSeconds(runVal1, runVal2) {
    let runDate2
    if (runVal2) {
        runDate2 = new Date(runVal2).getTime()
    } else {
        runDate2 = new Date().getTime()
    }
    let runDate1 = new Date(runVal1).getTime()
    let num = Math.abs(runDate2 - runDate1)
    return formatMillisecondTime(num)
}

export function formatMillisecondTime(num) {
    let showInfo
    let leave1 = num % (24 * 3600 * 1000)    //计算天数后剩余的毫秒数
    let leave2 = leave1 % (3600 * 1000)       //计算小时数后剩余的毫秒数
    let leave3 = leave2 % (60 * 1000)     //计算分钟数后剩余的毫秒数
    let day = Math.floor(num / (24 * 3600 * 1000)) //计算相差天数
    let hour = Math.floor(leave1 / (3600 * 1000))//计算相差小时
    let minute = Math.floor(leave2 / (60 * 1000))//计算相差分钟
    let second = Math.round(leave3 / 1000) //计算相差秒
    //处理边界值
    if (second === 60) {
        second = 0
        minute += 1
    }
    if (minute === 60) {
        minute = 0
        hour += 1
    }
    if (hour === 24) {
        hour = 0
        day += 1
    }
    if (day > 0) {
        showInfo = `${day}天 ${hour}小时 ${minute}分 ${second}秒`
    } else if (hour > 0) {
        showInfo = `${hour}小时 ${minute}分 ${second}秒`
    } else if (minute > 0) {
        showInfo = `${minute}分 ${second}秒`
    } else {
        showInfo = `${second}秒`
    }
    return showInfo
}

export function formatJson(json) {
    if (typeof json === 'string') {
        try {
            return JSON.stringify(JSON.parse(json), null, 4)
        } catch (e) {
            return json
        }
    } else {
        return JSON.stringify(json, null, 4)
    }
}

export function isJsonString(json) {
    try {
        JSON.parse(json)
        return true
    } catch (e) {
        return false
    }
}

export function formatSize(size, initUnit) {
    if (!size) return 0
    const unit = ['bytes', 'kb', 'mb', 'gb', 'tb', 'pb']
    let index = unit.indexOf((initUnit || 'bytes').toLowerCase());
    while (size > 1024) {
        size = size / 1024
        index += 1
    }
    return Math.round(size * 100) / 100 + ' ' + (unit[index] === 'bytes' ? unit[index] : unit[index].toUpperCase())
}

export function stringify(c) {
    let r = ""
    for (let i of Object.keys(c)) {
        r += (i + '=' + c[i] + '&')
    }
    if (r.endsWith("&")) {
        r = r.slice(0, r.length - 1)
    }
    return r
}

export function timeFormatSeconds(time) {
    if (!time) {
        return
    }
    let d = new Date(time)
    let year = d.getFullYear()
    let month = d.getMonth() + 1
    let day = d.getDate()
    let hours = d.getHours()
    let min = d.getMinutes()
    let seconds = d.getSeconds()

    if (month < 10) month = '0' + month
    if (day < 10) day = '0' + day
    if (hours < 10) hours = '0' + hours
    if (min < 10) min = '0' + min
    if (seconds < 10) seconds = '0' + seconds

    return (year + '-' + month + '-' + day + ' ' + hours + ':' + min + ':' + seconds)
}

export const validateEmail = (email) => {
    const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
    return regex.test(email) && email.indexOf("..") < 0
}

export const getDaysDiff = (date1, date2) => {
    const oneDay = 24 * 60 * 60 * 1000 // 一天的毫秒数
    const timeDiff = Math.abs(new Date(date1).getTime() - new Date(date2).getTime())
    return Math.round(timeDiff / oneDay)
}

export const jsonp = (url, data) => {
    return new Promise(((resolve, reject) => {
        let dataString = url.indexOf("?") === -1 ? "?" : "&"
        let callback = `jsonpCB_${Date.now()}`
        url += `${dataString}callback=${callback}`
        if (data) {
            for (let k in data) {
                url += `&${k}=${data[k]}`
            }
        }
        let scriptNode = document.createElement("script")
        scriptNode.src = url

        window[callback] = (result) => {
            result ? resolve(result) : reject("no data")
            delete window[callback]
            document.body.removeChild(scriptNode)
        }

        scriptNode.addEventListener("error", () => {
            reject("接口返回数据失败")
            delete window[callback]
            document.body.removeChild(scriptNode)
        }, false)

        document.body.appendChild(scriptNode)
    }))
}

export function transferData(data) {
    function decryptData(data) {
        var indexOfVal1 = data.indexOf("/");
        var indexOfVal2 = data.indexOf("+");
        const position = indexOfVal1 > 0 && indexOfVal2 > 0 ? Math.min(indexOfVal1, indexOfVal2) + 1 : Math.max(indexOfVal1, indexOfVal2) + 1
        const secretKey = data.substr(position, 32)
        return decrypt(data.substr(position + 32), secretKey)
    }

    if (typeof data === 'string' && data.startsWith("$$")) {
        const rdata = decryptData(data.substr(2))
        try {
            return JSON.parse(rdata)
        } catch (e) {
            return rdata
        }
    } else if (typeof data === 'object' && typeof data.data === 'string' && data.data.startsWith("$$")) {
        const rdata = decryptData(data.data.substr(2))
        let finalData
        try {
            finalData = JSON.parse(rdata)
        } catch (e) {
            finalData = rdata
        }
        data.data = finalData
        return data
    } else {
        return data
    }
}

export const macOs = navigator.userAgent.indexOf('Macintosh') !== -1

export const mobile = /(iPhone|Mobile|Android)/.test(navigator.userAgent)

export function getFontFamily() {
    if (macOs) {
        return 'font2, cursive, monospace'
    } else {
        return 'font2, Monaco, Menlo, Ubuntu Mono, Consolas, source-code-pro, monospace, Microsoft Yahei, Hiragino Sans GB, Heiti SC, WenQuanYi Micro Hei, sans-serif'
    }
}

export const getLimit = (point) => {
    if (!point) point = 0
    let lv = 1
    for (let activeDay of getPointInfo()) {
        if (point <= activeDay.point) {
            break
        }
        lv = activeDay.lv + 1
    }
    return {lv: lv, total: lv * 100, count: lv}
}

export const getPointInfo = () => {
    let lv = 1
    let activeDay = 0
    const activeDays = []
    while (lv < 10) {
        const increase = (lv + 5) * lv
        activeDay += increase
        const map = {"lv": lv, "point": activeDay}
        activeDays.push(map)
        lv++
    }
    return activeDays
}

export const getElementSize = (el, prop) => {
    const element = unrefElement(el)
    if (!el || !element) return {}
    const rect = element.getBoundingClientRect()
    return prop ? rect[prop] : rect
}

const RandomKey = 'randomKey';

export function randomKey(length) {
    if (!length || isNaN(parseInt(length))) {
        length = 16
    }
    let chars = ['2', '3', '4', '5', '6', '7', '8', '9',
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    let nums = ""
    for (let i = 0; i < length; i++) {//这里是几位就要在这里不改变
        let id = parseInt((Math.random() * 54) + '');
        nums += chars[id]
    }
    return nums
}

export function generateRandomNumber(length) {
    let num = Math.floor(Math.random() * Math.pow(10, length - 1) * 9); // 生成一个比10^(length-1) * 9小的随机数
    num += Math.pow(10, length - 1); // 加上10^(length-1)以确保数字长度正确
    return parseInt(String(num).slice(-length)); // 转换为字符串并截取最后length位
}

export function setRandomKey() {
    const key = randomKey()
    localStorage.setItem(RandomKey, key)
    return key
}

export function getRandomKey() {
    return localStorage.getItem(RandomKey) || null
}

export function removeRandomKey() {
    return localStorage.removeItem(RandomKey)
}

export const checkUrl = () => {
    return true
}

export function getIpAddress(row) {
    if (row.ipInfo && row.ipInfo.data) {
        if (row.ipInfo.data.prov === row.ipInfo.data.city) {
            return row.ipInfo.data.prov + row.ipInfo.data.district
        }
        return row.ipInfo.data.prov + row.ipInfo.data.city + row.ipInfo.data.district
    }
    return ""
}

export const emptyTriggerRule = {
    validator: (_rules, _value, callback) => {
        callback()
    }, trigger: ""
}

const countChineseCharacters = (str) => {
    var pattern = /[\u4e00-\u9fff]/g;
    var matches = str.match(pattern);
    if (matches) {
        return matches.length;
    } else {
        return 0;
    }
}

export const calcTextWidth = (text) => {
    const totalSize = text.length + 1
    const chineseSize = countChineseCharacters(text)
    return (totalSize - chineseSize + chineseSize * 2) * 8 + 70

}
import JSEncrypt from "jsencrypt"
import {publicKey} from "@/utils/constant"
import {decrypt as jsencrypt} from "@/utils/jsencrypt"

export function pbEncrypt(obj) {
    let encrypt = new JSEncrypt();
    encrypt.setPublicKey(publicKey.value);
    return encrypt.encrypt(obj);
}

export const pbDecrypt = (obj) => {
    const split = obj.split('oc56d+d87d/l8==8e9')
    let decryptText = ''
    for (let text of split) {
        decryptText += jsencrypt(text, publicKey.value)
    }
    return decryptText
}

export const once = function (el, event, fn) {
    const listener = function () {
        if (fn) {
            fn.apply(this, arguments);
        }
        off(el, event, listener);
    };
    on(el, event, listener);
};

export const off = (function () {
    if (document.removeEventListener) {
        return function (element, event, handler) {
            if (element && event) {
                element.removeEventListener(event, handler, false);
            }
        };
    } else {
        return function (element, event, handler) {
            if (element && event) {
                element.detachEvent('on' + event, handler);
            }
        };
    }
})();

export const on = (function () {
    if (document.addEventListener) {
        return function (element, event, handler) {
            if (element && event && handler) {
                element.addEventListener(event, handler, false);
            }
        };
    } else {
        return function (element, event, handler) {
            if (element && event && handler) {
                element.attachEvent('on' + event, handler);
            }
        };
    }
})();

import * as ElIcon from '@element-plus/icons-vue'
import {isArray} from '@vue/shared'

export const getIcon = (icon) => {
    icon = (icon || '').replace("el-icon-", "").replace(/\b[a-z]/g, function (match) {
        return match.toUpperCase();
    })
    return ElIcon[icon]
}

export const loadFont = (font) => {
    const arr = isArray(font)
    if (arr) {
        for (let f of font) {
            const regex = /\/([^\/]+)\.[^\/]+$/;
            // 创建一个新的FontFace对象
            const fontFace = new FontFace(f.match(regex)?.[1], `url(${f})`, {
                weight: 'normal',
                style: 'normal',
            })

            // 加载字体
            fontFace.load()
        }
    } else {
        loadFont([font])
    }
}

export function getLastDomain(domain) {
    if (!domain || !domain.includes('.')) return null;
    const match = domain.match(/[^.]+\.[^.]+$/);
    return match ? match[0] : null;
}